package zack.project.trigger.http;


import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.web.bind.annotation.*;
import zack.project.domain.activity.service.IRaffleActivityAccountQuotaService;
import zack.project.domain.strategy.model.entity.RaffleAwardEntity;
import zack.project.domain.strategy.model.entity.RaffleFactorEntity;
import zack.project.domain.strategy.model.entity.StrategyAwardEntity;
import zack.project.domain.strategy.model.valobj.RuleWeightVO;
import zack.project.domain.strategy.service.IRaffleAward;
import zack.project.domain.strategy.service.IRaffleRule;
import zack.project.domain.strategy.service.IRaffleStrategy;
import zack.project.domain.strategy.service.armory.IStrategyArmory;
import zack.project.trigger.api.IRaffleStrategyService;
import zack.project.trigger.api.dto.*;
import zack.project.trigger.api.response.Response;
import zack.project.types.enums.ResponseCode;
import zack.project.types.exception.AppException;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author A1793
 */
@Slf4j
@RestController()
@CrossOrigin("${app.config.cross-origin}")
@RequestMapping("/api/${app.config.api-version}/raffle/strategy/")
@Service(version = "1.0")
public class RaffleStrategyController implements IRaffleStrategyService {

    @Resource
    IRaffleAward raffleAward;
    @Resource
    IStrategyArmory strategyArmory;
    @Resource
    IRaffleStrategy raffleStrategy;
    @Resource
    IRaffleRule raffleRule;
    @Resource
    IRaffleActivityAccountQuotaService activityAccountQuotaService;

    @RequestMapping(value = "query_raffle_award_list", method = RequestMethod.POST)
    @Override
    public Response<List<RaffleAwardListResponseDTO>> queryRaffleAwardList(@RequestBody RaffleAwardListRequestDTO request) {
        log.info("查询抽奖奖品列表配开始 userId:{} activityId：{}", request.getUserId(), request.getActivityId());

        try {
            //参数校验
            if (StringUtils.isBlank(request.getUserId()) || request.getActivityId() == null) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            //查询奖品配置
            List<StrategyAwardEntity> strategyAwardEntityList = raffleAward.
                    queryRaffleStrategyAwardListByActivityId(request.getActivityId());
            //查询具体配置
            String[] treeIds = strategyAwardEntityList.stream()
                    .map(StrategyAwardEntity::getRuleModels)
                    .filter(ruleModel -> ruleModel != null && !ruleModel.isEmpty())
                    .toArray(String[]::new);

            Map<String, Integer> ruleLockCountMap = raffleRule.queryAwardRuleLockCount(treeIds);

            Integer partakeCount = activityAccountQuotaService.
                    queryRaffleActivityAccountDayPartakeCount(request.getActivityId(), request.getUserId());


            List<RaffleAwardListResponseDTO> raffleAwardListResponseDTOS =
                    new ArrayList<>(strategyAwardEntityList.size());
            // 5. 查询抽奖次数 - 用户已经参与的抽奖次数
            for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntityList) {
                Integer awardLockCount = ruleLockCountMap.get(strategyAwardEntity.getRuleModels());
                RaffleAwardListResponseDTO raffleAwardListResponseDTO = RaffleAwardListResponseDTO.builder()
                        .awardId(strategyAwardEntity.getAwardId())
                        .awardTitle(strategyAwardEntity.getAwardTitle())
                        .awardSubtitle(strategyAwardEntity.getAwardSubtitle() == null ? "" : strategyAwardEntity.getAwardSubtitle())
                        .sort(strategyAwardEntity.getSort())
                        .awardRuleLockCount(awardLockCount == null ? 0 : awardLockCount)
                        .isAwardUnlock(awardLockCount == null || partakeCount >= awardLockCount)
                        .waitUnLockCount(awardLockCount == null || partakeCount >= awardLockCount ?
                                0 : awardLockCount - partakeCount)
                        .build();
                raffleAwardListResponseDTOS.add(raffleAwardListResponseDTO);
            }

            Response<List<RaffleAwardListResponseDTO>> response = Response.<List<RaffleAwardListResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleAwardListResponseDTOS)
                    .build();
            log.info("查询抽奖奖品列表配置完成 userId:{} activityId：{} response: {}", request.getUserId(), request.getActivityId(), JSON.toJSONString(response));

            return response;


        } catch (Exception e) {
            log.error("查询抽奖奖品列表配置失败 userId:{} activityId：{}", request.getUserId(), request.getActivityId(), e);

            return Response.<List<RaffleAwardListResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }


    }

    @RequestMapping(value = "strategy_armory", method = RequestMethod.GET)
    @Override
    public Response<Boolean> strategyArmory(@RequestParam Long strategyId) {
        try {
            log.info("抽奖策略装配开始 strategyId：{}", strategyId);
            boolean armoryStatus = strategyArmory.assembleLotteryStrategy(strategyId);
            Response<Boolean> response = Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(armoryStatus)
                    .build();
            log.info("抽奖策略装配完成 strategyId：{} response: {}", strategyId, JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("抽奖策略装配失败 strategyId：{}", strategyId, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }


    @RequestMapping(value = "random_raffle", method = RequestMethod.POST)
    @Override
    public Response<RaffleStrategyResponseDTO> randomRaffle(@RequestBody RaffleStrategyRequestDTO requestDTO) {

        try {
            log.info("随机抽奖开始 strategyId: {}", requestDTO.getStrategyId());

            RaffleAwardEntity raffleAwardEntity =
                    raffleStrategy.performRaffle(RaffleFactorEntity.builder()
                            .strategyId(requestDTO.getStrategyId())
                            .userId("system").build());

            RaffleStrategyResponseDTO raffleResponseDTO = RaffleStrategyResponseDTO.builder()
                    .awardId(raffleAwardEntity.getAwardId())
                    .awardIndex(raffleAwardEntity.getSort())
                    .build();
            Response<RaffleStrategyResponseDTO> build = Response.<RaffleStrategyResponseDTO>builder().code(ResponseCode.SUCCESS.getCode()).info(ResponseCode.SUCCESS.getInfo()).data(raffleResponseDTO).build();
            log.info("随机抽奖完成 strategyId: {} response: {}", requestDTO.getStrategyId(), JSON.toJSONString(build));

            return build;
        } catch (AppException e) {
            log.error("随机抽奖失败 strategyId：{} {}", requestDTO.getStrategyId(), e.getInfo());
            return Response.<RaffleStrategyResponseDTO>builder()
                    .code(e.getCode())
                    .info(e.getInfo())
                    .build();
        } catch (Exception e) {
            log.error("随机抽奖失败 strategyId：{}", requestDTO.getStrategyId(), e);
            return Response.<RaffleStrategyResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    @RequestMapping(value = "query_raffle_strategy_rule_weight", method = RequestMethod.POST)

    @Override
    public Response<List<RaffleStrategyRuleWeightResponseDTO>> queryRaffleStrategyRuleWeight(@RequestBody RaffleStrategyRuleWeightRequestDTO request) {

        try {
            //参数判断
            if (StringUtils.isBlank(request.getUserId()) || request.getActivityId() == null) {

                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            Integer totalCount = activityAccountQuotaService.queryRaffleActivityAccountPartakeCount(request.getActivityId(), request.getUserId());

            List<RuleWeightVO> ruleWeightVOS = raffleRule.queryAwardRuleWeightByActivityId(request.getActivityId());
            List<RaffleStrategyRuleWeightResponseDTO> raffleStrategyRuleWeightList = new ArrayList<>();

            for (RuleWeightVO ruleWeightVO : ruleWeightVOS) {

                List<RaffleStrategyRuleWeightResponseDTO.StrategyAward> strategyAwards = new ArrayList<>();
                List<RuleWeightVO.Award> awardList = ruleWeightVO.getAwardList();

                for (RuleWeightVO.Award award : awardList) {
                    RaffleStrategyRuleWeightResponseDTO.StrategyAward strategyAward = new RaffleStrategyRuleWeightResponseDTO.StrategyAward();
                    strategyAward.setAwardId(award.getAwardId());
                    strategyAward.setAwardTitle(award.getAwardTitle());
                    strategyAwards.add(strategyAward);
                }
                RaffleStrategyRuleWeightResponseDTO raffleStrategyRuleWeightResponseDTO = new RaffleStrategyRuleWeightResponseDTO();
                raffleStrategyRuleWeightResponseDTO.setRuleWeightCount(ruleWeightVO.getWeight());
                raffleStrategyRuleWeightResponseDTO.setAwardList(strategyAwards);
                raffleStrategyRuleWeightResponseDTO.setUserActivityAccountTotalUseCount(totalCount);
                raffleStrategyRuleWeightList.add(raffleStrategyRuleWeightResponseDTO);
            }

            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleStrategyRuleWeightList)
                    .build();
        } catch (Exception e) {
            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }


    }
}
